package com.yzg.simple.netty.officialchat.server;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * @author misterWei
 * @mailbox mynameisweiyan@gmail.com
 */
//由于已经指定了编码器和解码器,所以泛型直接就是String 类型
public class NettyOfficialTcpServerHandler extends SimpleChannelInboundHandler<String> {

    /**
     * 这句话很有含义
     * 1. 是用来装载所有客户端的Channel;
     * 2. 在客户端如果离线就需要删除,如果用List 还需要循环遍历,如果用这个全局的ChannelGroup 就有监听机制,那个客户端断开连接就会清除自己的Channel;
     * 3.并且能够统一管理,群发什么的都非常方便
     */
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
/**
 * 如果用于私聊,就可以再用一个Map key --> 标识 value --> channel
 *              或者再用一个Map key -->  User value --> channel
 *               太简单了,不做简述
 */


    /**
     * 读取客户端的信息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel channel = ctx.channel();
        //群发消息
        channelGroup.forEach(channels ->{
            if (channels != channel) channels.writeAndFlush(channel.remoteAddress()+" :"+msg);
        });

    }

    /**
     * 客户端处于活动状态
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress()+" 上线了~~");
    }

    /**
     * 客户端不处于活动状态
     * @param ctx
     * @throws Exception
     */

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress()+" 离线了~~");
    }

    /**
     *  处理异常关闭该管道
     * @param ctx
     * @param cause
     * @throws Exception
     */

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("[异常产生为:]" + cause.getMessage());
    }

    /**
     * 表示连接建立，一旦连接，第一个被执行
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        //writeAndFlush 是由channelGroup 管理的所以,调用此方法,内部自己会循环写出
        if (channelGroup.size()!= 0) channelGroup.writeAndFlush(channel.remoteAddress()+ " 加入了聊天室~~");
        channelGroup.add(channel);
    }

    /**
    * 客户端断开连接的时候触发
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println(channelGroup.size());
        channelGroup.writeAndFlush(ctx.channel().remoteAddress()+" 离线了~~~");
    }
}
